package com.oncliedisk.administrator.utils;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.oncliedisk.administrator.model.FileTaskModel;
import com.vdisk.android.ComplexUploadHandler;
import com.vdisk.net.VDiskAPI;
import com.vdisk.net.VDiskAPI.Entry;
import com.vdisk.net.exception.VDiskException;
import com.vdisk.net.exception.VDiskFileNotFoundException;
import com.vdisk.net.exception.VDiskFileSizeException;
import com.vdisk.net.exception.VDiskIOException;
import com.vdisk.net.exception.VDiskParseException;
import com.vdisk.net.exception.VDiskPartialFileException;
import com.vdisk.net.exception.VDiskServerException;
import com.vdisk.net.exception.VDiskUnlinkedException;

import java.io.File;

/**
 * Here we show uploading a large file in a background thread, trying to show
 * typical exception handling and flow of control for an app that uploads a file
 * from VDisk.
 */
public class LargeFileUpload extends AsyncTask<Void, Long, Boolean> {

    private static final String TAG = "LargeFileUpload";
    private VDiskAPI<?> mApi;
    private String mPath;
    private File mFile;
    private long mFileLen;
    private Context mContext;
    private String mErrorMsg;
    private String mSrcPath;
    private ComplexUploadHandler handler;
    private com.oncliedisk.administrator.interfaces.onDownFileListener onDownFileListener;
    private File file;
    public FileTaskModel model;
    private Entry metadata;
    public LargeFileUpload(Context context, FileTaskModel model, VDiskAPI<?> api, com.oncliedisk.administrator.interfaces.onDownFileListener onDownFileListener) {
        mContext = context.getApplicationContext();
        file = new File(model.getLocalPath());
        mSrcPath = file.getAbsolutePath();
        this.onDownFileListener = onDownFileListener;
        mFileLen = file.length();
        mApi = api;
        mPath = model.getPath();
        mFile = file;
        this.model = model;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        Log.i("info", "开始执行下载");
        try {
            if (!mPath.endsWith("/")) {
                mPath = mPath + "/";
            }

            String desPath = mPath + mFile.getName();

            handler = new ComplexUploadHandler(mContext) {
                @Override
                public void onProgress(long bytes, long total) {
                    publishProgress(bytes);
                }

                @Override
                public void startedWithStatus(ComplexUploadStatus status) {
                    switch (status) {
                        case ComplexUploadStatusLocateHost:
                            Log.d(TAG, "Getting the nearest host...");
                            break;
                        case ComplexUploadStatusCreateFileSHA1:
                            Log.d(TAG, "Creating the sha1 of file");
                            break;
                        case ComplexUploadStatusInitialize:
                            Log.d(TAG, "Signing each segment of file...");
                            break;
                        case ComplexUploadStatusCreateFileMD5s:
                            Log.d(TAG, "Creating each segment's md5...");
                            break;
                        case ComplexUploadStatusUploading:
                            Log.d(TAG, "Uploading one segment...");
                            break;
                        case ComplexUploadStatusMerging:
                            Log.d(TAG, "File Merging...");
                            break;
                        default:
                            break;
                    }
                }

                @Override
                public void finishedWithMetadata(Entry metadatas) {
                    metadata = metadatas;
                    Log.d(TAG, "Upload success : " + metadata.fileName());
                }
            };

            mApi.putLargeFileOverwriteRequest(mSrcPath, desPath,
                    mFile.length(), handler);

            return true;

        } catch (VDiskUnlinkedException e) {
            // This session wasn't authenticated properly or user unlinked
            mErrorMsg = "This app wasn't authenticated properly.";
        } catch (VDiskFileSizeException e) {
            // File size too big to upload via the API
            mErrorMsg = "This file is too big to upload";
        } catch (VDiskPartialFileException e) {
            // We canceled the operation
            mErrorMsg = "Upload canceled";
        } catch (VDiskServerException e) {
            // Server-side exception. These are examples of what could happen,
            // but we don't do anything special with them here.
            if (e.error == VDiskServerException._401_UNAUTHORIZED) {
                // Unauthorized, so we should unlink them. You may want to
                // automatically log the user out in this case.
            } else if (e.error == VDiskServerException._403_FORBIDDEN) {
                // Not allowed to access this
            } else if (e.error == VDiskServerException._404_NOT_FOUND) {
                // path not found (or if it was the thumbnail, can't be
                // thumbnailed)
            } else if (e.error == VDiskServerException._507_INSUFFICIENT_STORAGE) {
                // user is over quota
            } else {
                // Something else
            }
            // This gets the VDisk error, translated into the user's language
            mErrorMsg = e.body.userError;
            if (mErrorMsg == null) {
                mErrorMsg = e.body.error;
            }
            e.printStackTrace();
        } catch (VDiskIOException e) {
            // Happens all the time, probably want to retry automatically.
            e.printStackTrace();
            mErrorMsg = "Network error.  Try again.";
        } catch (VDiskParseException e) {
            // Probably due to VDisk server restarting, should retry
            mErrorMsg = "VDisk error.  Try again.";
            e.printStackTrace();
        } catch (VDiskFileNotFoundException e) {
            mErrorMsg = "File not found.";
            e.printStackTrace();
        } catch (VDiskException e) {
            // Unknown error
            mErrorMsg = "Unknown error.  Try again.";
            e.printStackTrace();
        }
        return false;
    }

    @Override
    protected void onProgressUpdate(Long... progress) {
        int percent = (int) (100.0 * (double) progress[0] / mFileLen + 0.5);
        onDownFileListener.onProgress(percent, ExploerLoadSdFileTask.formateFileSize(progress[0]), model);
    }

    public void closeThead() {
        if (handler != null) {
            handler.abort();
        }
    }

    @Override
    protected void onPostExecute(Boolean result) {
        if (result) {
            onDownFileListener.onDownFinish(model,metadata);
        } else {
            onDownFileListener.onDownFail(mErrorMsg);
        }
    }
}
